import * as THREE from "three";
import { StereoEffect } from "three/addons/effects/StereoEffect.js";
import { VRButton } from "three/addons/webxr/VRButton.js";
import { RollerCoasterGeometry, RollerCoasterShadowGeometry, RollerCoasterLiftersGeometry, TreesGeometry, SkyGeometry } from "three/addons/misc/RollerCoaster.js";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { OutlineEffect } from "three/addons/effects/OutlineEffect.js";
import { MMDLoader } from "three/addons/loaders/MMDLoader.js";
import { MMDAnimationHelper } from "three/addons/animation/MMDAnimationHelper.js";
import { FirstPersonControls } from "three/addons/controls/FirstPersonControls.js";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { FontLoader } from "three/addons/loaders/FontLoader.js";
import { TextGeometry } from "three/addons/geometries/TextGeometry.js";
import { ShadowMapViewer } from "three/addons/utils/ShadowMapViewer.js";
import { RGBELoader } from "three/addons/loaders/RGBELoader.js";
import { Water } from "three/addons/objects/Water.js";
import { Sky } from "three/addons/objects/Sky.js";

type CubeTexturePaths = [string, string, string, string, string, string];

type FunfairObject = THREE.Mesh & { originalRotationY?: number };

//房子背景
class House {
    private camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100000);
    private scene: THREE.Scene = new THREE.Scene();
    private renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer();
    private effect: StereoEffect | null = null;
    private spheres: THREE.Mesh[] = [];
    private mouseX: number = 0;
    private mouseY: number = 0;
    private windowHalfX: number = window.innerWidth / 2;
    private windowHalfY: number = window.innerHeight / 2;
    private geometry: THREE.SphereGeometry = new THREE.SphereGeometry(100, 32, 16);
    private timer: number = 0.0001 * Date.now();
    private container: HTMLElement | null = null;

    private readonly cubeTexturePaths: CubeTexturePaths = ["/img/px.jpg", "/img/nx.jpg", "/img/py.jpg", "/img/ny.jpg", "/img/pz.jpg", "/img/nz.jpg"];
    constructor(id: string) {
        this.container = document.getElementById(id);
        this.load();
    }

    private load(): void {
        if (!this.container) {
            console.error(`ID属性未找到！`);
            return;
        }
        this.camera.position.z = 3200;
        this.scene.background = new THREE.CubeTextureLoader().load(this.cubeTexturePaths);
        const textureCube = new THREE.CubeTextureLoader().load(this.cubeTexturePaths);
        textureCube.mapping = THREE.CubeRefractionMapping;
        const material = new THREE.MeshBasicMaterial({ color: 0xffffff, envMap: textureCube, refractionRatio: 0.95 });

        for (let i = 0; i < 500; i++) {
            const mesh = new THREE.Mesh(this.geometry, material);
            mesh.position.x = Math.random() * 10000 - 5000;
            mesh.position.y = Math.random() * 10000 - 5000;
            mesh.position.z = Math.random() * 10000 - 5000;
            mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * 3 + 1;
            this.scene.add(mesh);
            this.spheres.push(mesh);
        }
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.container.appendChild(this.renderer.domElement);

        this.effect = new StereoEffect(this.renderer);
        this.effect.setSize(window.innerWidth, window.innerHeight);

        window.addEventListener("resize", this.onWindowResize);

        this.animate();
    }
    private onWindowResize = (): void => {
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        this.effect?.setSize(window.innerWidth, window.innerHeight);
    };
    private animate = (): void => {
        requestAnimationFrame(this.animate);
        this.render();
        this.mousemove();
    };
    private render = (): void => {
        this.camera.position.x += (this.mouseX - this.camera.position.x) * 0.05;
        this.camera.position.y += (-this.mouseY - this.camera.position.y) * 0.05;
        this.camera.lookAt(this.scene.position);

        for (let i = 0, il = this.spheres.length; i < il; i++) {
            const sphere = this.spheres[i];
            sphere.position.x = 5000 * Math.cos(this.timer + i);
            sphere.position.y = 5000 * Math.sin(this.timer + i * 1.1);
        }
        this.effect?.render(this.scene, this.camera);
    };
    private mousemove = (): void => {
        document.addEventListener("mousemove", this.onDocumentMouseMove);
    };
    private onDocumentMouseMove = (event: any): void => {
        this.mouseX = (event.clientX - this.windowHalfX) * 10;
        this.mouseY = (event.clientY - this.windowHalfY) * 10;
    };
    public dispose(): void {
        window.removeEventListener("resize", this.onWindowResize.bind(this));
        document.removeEventListener("mousemove", this.onDocumentMouseMove.bind(this));

        if (this.container && this.renderer?.domElement) {
            this.container.removeChild(this.renderer.domElement);
        }

        // Dispose of Three.js objects
        this.spheres.forEach((sphere) => {
            sphere.geometry.dispose();
            if (Array.isArray(sphere.material)) {
                sphere.material.forEach((m) => m.dispose());
            } else {
                sphere.material.dispose();
            }
        });

        this.renderer?.dispose();
    }
}

//过山车背景
class Coaster {
    // 属性声明
    private mesh: THREE.Mesh | null = null;
    private material: THREE.Material | null = null;
    private curve: {
        getPointAt: (t: number) => THREE.Vector3;
        getTangentAt: (t: number) => THREE.Vector3;
    } | null = null;
    private renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer({ antialias: true });
    private scene: THREE.Scene = new THREE.Scene();
    private light: THREE.HemisphereLight = new THREE.HemisphereLight(0xfff0f0, 0x606060, 3);
    private train: THREE.Object3D = new THREE.Object3D();
    private camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 500);
    private geometry: THREE.BufferGeometry | null = null;
    private vertex: THREE.Vector3 = new THREE.Vector3();
    private funfairs: FunfairObject[] = [];
    private position: THREE.Vector3 = new THREE.Vector3();
    private tangent: THREE.Vector3 = new THREE.Vector3();
    private lookAt: THREE.Vector3 = new THREE.Vector3();
    private velocity: number = 0;
    private progress: number = 0;
    private prevTime: number = performance.now();
    private container: HTMLElement | null = null;

    constructor(id: string) {
        this.container = document.getElementById(id);
        this.load();
    }

    private load(): void {
        if (!this.container) {
            console.error(`ID属性未找到！`);
            return;
        }

        this.setupRenderer();
        this.setupScene();
        this.setupEnvironment();
        this.setupTrack();
        this.setupAttractions();
        this.setupEventListeners();
    }

    private setupRenderer(): void {
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.renderer.xr.enabled = true;
        this.renderer.xr.setReferenceSpaceType("local");

        if (this.container) {
            this.container.appendChild(this.renderer.domElement);
            this.container.appendChild(VRButton.createButton(this.renderer));
        }
    }

    private setupScene(): void {
        this.scene.background = new THREE.Color(0xf0f0ff);
        this.light.position.set(1, 1, 1);
        this.scene.add(this.light);
        this.scene.add(this.train);
        this.train.add(this.camera);
    }

    private setupEnvironment(): void {
        // 地面
        this.geometry = new THREE.PlaneGeometry(500, 500, 15, 15);
        this.geometry.rotateX(-Math.PI / 2);

        const positions = this.geometry.attributes.position.array as Float32Array;
        for (let i = 0; i < positions.length; i += 3) {
            this.vertex.fromArray(positions, i);

            this.vertex.x += Math.random() * 10 - 5;
            this.vertex.z += Math.random() * 10 - 5;

            const distance = this.vertex.distanceTo(this.scene.position) / 5 - 25;
            this.vertex.y = Math.random() * Math.max(0, distance);

            this.vertex.toArray(positions, i);
        }

        this.geometry.computeVertexNormals();
        this.material = new THREE.MeshLambertMaterial({ color: 0x407000 });
        this.mesh = new THREE.Mesh(this.geometry, this.material);
        this.scene.add(this.mesh);

        // 树木
        this.geometry = new TreesGeometry(this.mesh);
        this.material = new THREE.MeshBasicMaterial({
            side: THREE.DoubleSide,
            vertexColors: true,
        });
        this.mesh = new THREE.Mesh(this.geometry, this.material);
        this.scene.add(this.mesh);

        // 天空
        this.geometry = new SkyGeometry();
        this.material = new THREE.MeshBasicMaterial({ color: 0xffffff });
        this.mesh = new THREE.Mesh(this.geometry, this.material);
        this.scene.add(this.mesh);
    }

    private setupTrack(): void {
        const PI2 = Math.PI * 2;

        this.curve = {
            getPointAt: (t: number) => {
                t = t * PI2;
                const x = Math.sin(t * 3) * Math.cos(t * 4) * 50;
                const y = Math.sin(t * 10) * 2 + Math.cos(t * 17) * 2 + 5;
                const z = Math.sin(t) * Math.sin(t * 4) * 50;
                return new THREE.Vector3(x, y, z).multiplyScalar(2);
            },

            getTangentAt: (t: number) => {
                const delta = 0.0001;
                return this.curve!.getPointAt(Math.min(1, t + delta))
                    .clone()
                    .sub(this.curve!.getPointAt(Math.max(0, t - delta)))
                    .normalize();
            },
        };

        // 过山车轨道
        this.geometry = new RollerCoasterGeometry(this.curve, 1500);
        this.material = new THREE.MeshPhongMaterial({ vertexColors: true });
        this.mesh = new THREE.Mesh(this.geometry, this.material);
        this.scene.add(this.mesh);

        // 轨道支撑
        this.geometry = new RollerCoasterLiftersGeometry(this.curve, 100);
        this.material = new THREE.MeshPhongMaterial();
        this.mesh = new THREE.Mesh(this.geometry, this.material);
        this.mesh.position.y = 0.1;
        this.scene.add(this.mesh);

        // 轨道阴影
        this.geometry = new RollerCoasterShadowGeometry(this.curve, 500);
        this.material = new THREE.MeshBasicMaterial({
            color: 0x305000,
            depthWrite: false,
            transparent: true,
        });
        this.mesh = new THREE.Mesh(this.geometry, this.material);
        this.mesh.position.y = 0.1;
        this.scene.add(this.mesh);
    }

    private setupAttractions(): void {
        // 游乐设施1
        this.geometry = new THREE.CylinderGeometry(10, 10, 5, 15);
        this.material = new THREE.MeshLambertMaterial({ color: 0xff8080 });
        this.mesh = new THREE.Mesh(this.geometry, this.material);
        this.mesh.position.set(-80, 10, -70);
        this.mesh.rotation.x = Math.PI / 2;
        this.scene.add(this.mesh);
        this.funfairs.push(this.mesh as FunfairObject);

        // 游乐设施2
        this.geometry = new THREE.CylinderGeometry(5, 6, 4, 10);
        this.material = new THREE.MeshLambertMaterial({ color: 0x8080ff });
        this.mesh = new THREE.Mesh(this.geometry, this.material);
        this.mesh.position.set(50, 2, 30);
        this.scene.add(this.mesh);
        this.funfairs.push(this.mesh as FunfairObject);
    }

    private setupEventListeners(): void {
        window.addEventListener("resize", this.onWindowResize.bind(this));
        this.renderer.setAnimationLoop(this.render.bind(this));
    }

    private render(): void {
        const time = performance.now();
        const delta = time - this.prevTime;

        // 旋转游乐设施
        this.funfairs.forEach((funfair) => {
            funfair.rotation.y = time * 0.0004;
        });

        // 更新过山车位置
        this.progress += this.velocity;
        this.progress = this.progress % 1;

        if (this.curve) {
            this.position.copy(this.curve.getPointAt(this.progress));
            this.position.y += 0.3;

            this.train.position.copy(this.position);

            this.tangent.copy(this.curve.getTangentAt(this.progress));

            this.velocity -= this.tangent.y * 0.0000001 * delta;
            this.velocity = Math.max(0.00004, Math.min(0.0002, this.velocity));

            this.train.lookAt(this.lookAt.copy(this.position).sub(this.tangent));
        }

        this.renderer.render(this.scene, this.camera);
        this.prevTime = time;
    }

    private onWindowResize(): void {
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(window.innerWidth, window.innerHeight);
    }

    public dispose(): void {
        window.removeEventListener("resize", this.onWindowResize.bind(this));
        this.renderer.setAnimationLoop(null);

        if (this.container && this.renderer.domElement.parentNode === this.container) {
            this.container.removeChild(this.renderer.domElement);
        }

        // 清理所有几何体和材质
        [this.scene, this.train].forEach((obj) => {
            obj.traverse((child) => {
                if (child instanceof THREE.Mesh) {
                    child.geometry.dispose();
                    if (Array.isArray(child.material)) {
                        child.material.forEach((m) => m.dispose());
                    } else {
                        child.material.dispose();
                    }
                }
            });
        });

        this.renderer.dispose();
    }
}

//跳舞背景
class Dancer {
    // 属性声明
    private mesh: any = null;
    private effect: any = null;
    private ikHelper: any = null;
    private physicsHelper: any = null;
    private renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer({ antialias: true });
    private helper: any = new MMDAnimationHelper({ afterglow: 2.0 });
    private gridHelper: THREE.PolarGridHelper = new THREE.PolarGridHelper(30, 0);
    private loader: MMDLoader = new MMDLoader();
    private directionalLight: THREE.DirectionalLight = new THREE.DirectionalLight(0xffffff, 3);
    private ambientLight: THREE.AmbientLight = new THREE.AmbientLight(0xaaaaaa, 3);
    private camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
    private scene: THREE.Scene = new THREE.Scene();
    private clock: THREE.Clock = new THREE.Clock();
    private controls: OrbitControls | null = null;
    private container: HTMLElement | null = null;

    constructor(id: string) {
        this.container = document.getElementById(id);
        this.load();
    }

    private load(): void {
        if (!this.container) {
            console.error(`ID属性未找到！`);
            return;
        }

        this.setupScene();
        this.setupRenderer();
        this.setupControls();
        this.loadModel();
        this.setupEventListeners();
        this.animate();
    }

    private setupScene(): void {
        this.camera.position.z = 30;
        this.scene.background = new THREE.Color(0xffffff);

        this.gridHelper.position.y = -10;
        this.scene.add(this.gridHelper);

        this.scene.add(this.ambientLight);

        this.directionalLight.position.set(-1, 1, 1).normalize();
        this.scene.add(this.directionalLight);
    }

    private setupRenderer(): void {
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.container?.appendChild(this.renderer.domElement);

        this.effect = new OutlineEffect(this.renderer);
    }

    private setupControls(): void {
        if (!this.renderer.domElement) return;

        this.controls = new OrbitControls(this.camera, this.renderer.domElement);
        this.controls.minDistance = 10;
        this.controls.maxDistance = 100;
    }

    private loadModel(): void {
        this.loader.loadWithAnimation(
            "/file/miku_v2.pmd",
            ["/file/wavefile_v2.vmd"],
            (mmd: any) => {
                this.mesh = mmd.mesh;
                this.mesh.position.y = -10;
                this.scene.add(this.mesh);
                this.helper.add(this.mesh, { animation: mmd.animation, physics: true });
                this.ikHelper = this.helper.objects.get(this.mesh)?.ikSolver.createHelper();
                this.ikHelper.visible = false;
                this.scene.add(this.ikHelper);

                this.physicsHelper = this.helper.objects.get(this.mesh)?.physics?.createHelper();
                this.physicsHelper.visible = false;
                this.scene.add(this.physicsHelper);
            },
            undefined,
            undefined
        );
    }

    private setupEventListeners(): void {
        window.addEventListener("resize", this.onWindowResize.bind(this));
    }

    private onWindowResize = (): void => {
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        this.effect?.setSize(window.innerWidth, window.innerHeight);
    };

    private animate = (): void => {
        requestAnimationFrame(this.animate);

        const delta = this.clock.getDelta();
        this.helper.update(delta);

        if (this.effect) {
            this.effect.render(this.scene, this.camera);
        }

        this.controls?.update();
    };

    public dispose(): void {
        // 移除事件监听器
        window.removeEventListener("resize", this.onWindowResize);

        // 停止动画循环
        cancelAnimationFrame(this.animate as unknown as number);

        // 移除渲染器DOM元素
        if (this.container && this.renderer.domElement.parentNode === this.container) {
            this.container.removeChild(this.renderer.domElement);
        }

        // 清理控制器
        this.controls?.dispose();

        // 清理OutlineEffect - 需要手动清理而不是调用dispose()
        if (this.effect) {
            // 1. 停止使用它
            this.effect = null;
            // 2. 恢复原始渲染器
            this.renderer.dispose();
            this.renderer = new THREE.WebGLRenderer({ antialias: true });
        } else {
            this.renderer.dispose();
        }

        // 清理模型和辅助对象
        if (this.mesh) {
            this.scene.remove(this.mesh);
            this.helper.remove(this.mesh);

            // 清理材质
            if (Array.isArray(this.mesh.material)) {
                this.mesh.material.forEach((material: any) => material?.dispose());
            } else {
                this.mesh.material.dispose();
            }

            // 清理几何体
            this.mesh.geometry.dispose();
        }

        if (this.ikHelper) this.scene.remove(this.ikHelper);
        if (this.physicsHelper) this.scene.remove(this.physicsHelper);

        // 清理其他资源
        this.gridHelper.dispose();
        if (this.helper) {
            this.helper = new MMDAnimationHelper({ afterglow: 2.0 });
        }
    }

    // 辅助方法
    public toggleIKHelperVisibility(visible: boolean): void {
        if (this.ikHelper) {
            this.ikHelper.visible = visible;
        }
    }

    public togglePhysicsHelperVisibility(visible: boolean): void {
        if (this.physicsHelper) {
            this.physicsHelper.visible = visible;
        }
    }

    public setOutlineEnabled(enabled: boolean): void {
        if (this.effect) {
            this.effect.enabled = enabled;
        }
    }
}

//多彩圆点
class Points {
    // 属性声明
    private camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 2, 2000);
    private scene: THREE.Scene = new THREE.Scene();
    private renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer();
    private material: THREE.PointsMaterial | null = null;
    private particles: THREE.Points | null = null;
    private mouseX: number = 0;
    private mouseY: number = 0;
    private windowHalfX: number = window.innerWidth / 2;
    private windowHalfY: number = window.innerHeight / 2;
    private container: HTMLElement | null = null;
    constructor(id: string) {
        this.container = document.getElementById(id);
        this.load();
    }
    public load(): void {
        if (!this.container) {
            console.error(`ID属性未找到！`);
            return;
        }

        this.setupScene();
        this.setupParticles();
        this.setupRenderer();
        this.setupEventListeners();
        this.animate();
    }
    private setupScene(): void {
        this.camera.position.z = 1000;
        this.scene.fog = new THREE.FogExp2(0x000000, 0.001);
    }

    private setupParticles(): void {
        const geometry = new THREE.BufferGeometry();
        const vertices: number[] = [];

        // 创建随机粒子位置
        for (let i = 0; i < 10000; i++) {
            vertices.push(2000 * Math.random() - 1000, 2000 * Math.random() - 1000, 2000 * Math.random() - 1000);
        }

        geometry.setAttribute("position", new THREE.Float32BufferAttribute(vertices, 3));

        // 加载粒子纹理
        const sprite = new THREE.TextureLoader().load("/img/disc.png");
        sprite.colorSpace = THREE.SRGBColorSpace;

        // 创建粒子材质
        this.material = new THREE.PointsMaterial({
            size: 35,
            sizeAttenuation: true,
            map: sprite,
            alphaTest: 0.5,
            transparent: true,
        });
        this.material.color.setHSL(1.0, 0.3, 0.7, THREE.SRGBColorSpace);

        // 创建粒子系统
        this.particles = new THREE.Points(geometry, this.material);
        this.scene.add(this.particles);
    }

    private setupRenderer(): void {
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.container?.appendChild(this.renderer.domElement);
    }

    private setupEventListeners(): void {
        if (!this.container) return;

        this.container.addEventListener("pointermove", this.onPointerMove.bind(this));
        window.addEventListener("resize", this.onWindowResize.bind(this));
    }

    private onPointerMove(event: PointerEvent): void {
        if (event.isPrimary === false) return;
        this.mouseX = event.clientX - this.windowHalfX;
        this.mouseY = event.clientY - this.windowHalfY;
    }

    private onWindowResize(): void {
        this.windowHalfX = window.innerWidth / 2;
        this.windowHalfY = window.innerHeight / 2;

        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();

        this.renderer.setSize(window.innerWidth, window.innerHeight);
    }

    private animate = (): void => {
        requestAnimationFrame(this.animate);
        this.render();
    };

    private render(): void {
        const time = Date.now() * 0.00005;

        // 更新相机位置
        this.camera.position.x += (this.mouseX - this.camera.position.x) * 0.05;
        this.camera.position.y += (-this.mouseY - this.camera.position.y) * 0.05;
        this.camera.lookAt(this.scene.position);

        // 更新粒子颜色
        if (this.material) {
            const h = ((360 * (1.0 + time)) % 360) / 360;
            this.material.color.setHSL(h, 0.5, 0.5);
        }

        this.renderer.render(this.scene, this.camera);
    }

    public dispose(): void {
        // 移除事件监听器
        if (this.container) {
            this.container.removeEventListener("pointermove", this.onPointerMove.bind(this));
        }
        window.removeEventListener("resize", this.onWindowResize.bind(this));

        // 停止动画循环
        cancelAnimationFrame(this.animate as unknown as number);

        // 移除渲染器DOM元素
        if (this.container && this.renderer.domElement.parentNode === this.container) {
            this.container.removeChild(this.renderer.domElement);
        }

        // 清理粒子系统
        if (this.particles) {
            this.scene.remove(this.particles);

            // 清理几何体
            this.particles.geometry.dispose();

            // 清理材质
            if (this.material) {
                this.material.dispose();
                if (this.material.map) {
                    this.material.map.dispose();
                }
            }
        }

        // 清理渲染器
        this.renderer.dispose();
    }
}

//万马奔腾
class Horse {
    // 常量定义
    private readonly SHADOW_MAP_WIDTH = 2048;
    private readonly SHADOW_MAP_HEIGHT = 1024;
    private readonly FLOOR = -250;
    private readonly NEAR = 10;
    private readonly FAR = 3000;

    // 场景属性
    private camera: THREE.PerspectiveCamera | null = null;
    private scene: THREE.Scene = new THREE.Scene();
    private renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer({ antialias: true });
    private light: THREE.DirectionalLight = new THREE.DirectionalLight(0xffffff, 3);
    private controls: FirstPersonControls | null = null;
    private mixer: THREE.AnimationMixer | null = null;
    private clock: THREE.Clock = new THREE.Clock();

    // 场景对象集合
    private meshs: THREE.Object3D[] = [];
    private morphs: THREE.Object3D[] = [];

    // HUD相关
    private lightShadowMapViewer: ShadowMapViewer | null = null;
    private showHUD = false;

    // 屏幕尺寸
    private screenWidth: number = window.innerWidth;
    private screenHeight: number = window.innerHeight;

    // 容器引用
    private container: HTMLElement | null = null;

    constructor(id: string) {
        this.container = document.getElementById(id);
        this.load();
    }

    private load(): void {
        if (!this.container) {
            console.error(`ID属性未找到！`);
            return;
        }

        this.setupCamera();
        this.setupScene();
        this.setupRenderer();
        this.setupControls();
        this.setupEventListeners();
        this.animate();
    }

    private setupCamera(): void {
        this.camera = new THREE.PerspectiveCamera(23, this.screenWidth / this.screenHeight, this.NEAR, this.FAR);
        this.camera.position.set(700, 50, 1900);
    }

    private setupScene(): void {
        // 场景基础设置
        this.scene.background = new THREE.Color(0x59472b);
        this.scene.fog = new THREE.Fog(0x59472b, 1000, this.FAR);

        // 环境光
        const ambient = new THREE.AmbientLight(0xffffff);
        this.scene.add(ambient);

        // 定向光设置
        this.light.position.set(0, 1500, 1000);
        this.light.castShadow = true;
        this.light.shadow.camera.top = 2000;
        this.light.shadow.camera.bottom = -2000;
        this.light.shadow.camera.left = -2000;
        this.light.shadow.camera.right = 2000;
        this.light.shadow.camera.near = 1200;
        this.light.shadow.camera.far = 2500;
        this.light.shadow.bias = 0.0001;
        this.light.shadow.mapSize.width = this.SHADOW_MAP_WIDTH;
        this.light.shadow.mapSize.height = this.SHADOW_MAP_HEIGHT;
        this.scene.add(this.light);

        // 创建HUD
        this.createHUD();

        // 创建场景内容
        this.createSceneContent();
    }

    private createHUD(): void {
        this.lightShadowMapViewer = new ShadowMapViewer(this.light);
        this.lightShadowMapViewer.position.x = 10;
        this.lightShadowMapViewer.position.y = this.screenHeight - this.SHADOW_MAP_HEIGHT / 4 - 10;
        this.lightShadowMapViewer.size.width = this.SHADOW_MAP_WIDTH / 4;
        this.lightShadowMapViewer.size.height = this.SHADOW_MAP_HEIGHT / 4;
        this.lightShadowMapViewer.update();
    }

    private createSceneContent(): void {
        // 创建地面
        const groundGeometry = new THREE.PlaneGeometry(100, 100);
        const planeMaterial = new THREE.MeshPhongMaterial({ color: 0xffdd99 });
        const ground = new THREE.Mesh(groundGeometry, planeMaterial);
        ground.position.set(0, this.FLOOR, 0);
        ground.rotation.x = -Math.PI / 2;
        ground.scale.set(100, 100, 100);
        ground.castShadow = false;
        ground.receiveShadow = true;
        this.scene.add(ground);
        this.meshs.push(ground);

        // 加载字体创建文本
        const loader = new FontLoader();
        loader.load(
            "/font/helvetiker_bold.typeface.json",
            (font) => {
                const textGeo = new TextGeometry("", {
                    font: font,
                    size: 200,
                    height: 50,
                    curveSegments: 12,
                    bevelThickness: 2,
                    bevelSize: 5,
                    bevelEnabled: true,
                });

                textGeo.computeBoundingBox();
                const textMaterial = new THREE.MeshPhongMaterial({
                    color: 0xff0000,
                    specular: 0xffffff,
                });

                const mesh = new THREE.Mesh(textGeo, textMaterial);
                const boundingBox = textGeo.boundingBox;

                if (boundingBox) {
                    mesh.position.x = -0.5 * (boundingBox.max.x - boundingBox.min.x);
                }

                mesh.position.y = this.FLOOR + 67;
                mesh.castShadow = true;
                mesh.receiveShadow = true;
                this.scene.add(mesh);
                this.meshs.push(mesh);
            },
            undefined,
            (error) => {
                console.error("字体加载失败:", error);
            }
        );

        // 创建立方体
        const cubes1 = new THREE.Mesh(new THREE.BoxGeometry(1500, 220, 150), planeMaterial);
        cubes1.position.y = this.FLOOR - 50;
        cubes1.position.z = 20;
        cubes1.castShadow = true;
        cubes1.receiveShadow = true;
        this.scene.add(cubes1);
        this.meshs.push(cubes1);

        const cubes2 = new THREE.Mesh(new THREE.BoxGeometry(1600, 170, 250), planeMaterial);
        cubes2.position.y = this.FLOOR - 50;
        cubes2.position.z = 20;
        cubes2.castShadow = true;
        cubes2.receiveShadow = true;
        this.scene.add(cubes2);
        this.meshs.push(cubes2);

        // 初始化动画混合器
        this.mixer = new THREE.AnimationMixer(this.scene);

        // 加载GLTF模型
        this.loadGLTFModels(planeMaterial);
    }

    private loadGLTFModels(_planeMaterial: THREE.Material): void {
        const gltfLoader = new GLTFLoader();

        // 加载马模型
        gltfLoader.load(
            "/file/Horse.glb",
            (gltf) => {
                const mesh = gltf.scene.children[0];
                const clip = gltf.animations[0];

                this.addMorph(mesh, clip, 550, 1, 100 - Math.random() * 1000, this.FLOOR, 300, true);
                this.addMorph(mesh, clip, 550, 1, 100 - Math.random() * 1000, this.FLOOR, 450, true);
                this.addMorph(mesh, clip, 550, 1, 100 - Math.random() * 1000, this.FLOOR, 600, true);
                this.addMorph(mesh, clip, 550, 1, 100 - Math.random() * 1000, this.FLOOR, -300, true);
                this.addMorph(mesh, clip, 550, 1, 100 - Math.random() * 1000, this.FLOOR, -450, true);
                this.addMorph(mesh, clip, 550, 1, 100 - Math.random() * 1000, this.FLOOR, -600, true);
            },
            undefined,
            (error) => {
                console.error("马模型加载失败:", error);
            }
        );

        // 加载其他动物模型
        gltfLoader.load("/file/Flamingo.glb", (gltf) => this.addMorph(gltf.scene.children[0], gltf.animations[0], 500, 1, 500 - Math.random() * 500, this.FLOOR + 350, 40, true));

        gltfLoader.load("/file/Stork.glb", (gltf) => this.addMorph(gltf.scene.children[0], gltf.animations[0], 350, 1, 500 - Math.random() * 500, this.FLOOR + 350, 340, true));

        gltfLoader.load("/file/Parrot.glb", (gltf) => this.addMorph(gltf.scene.children[0], gltf.animations[0], 450, 0.5, 500 - Math.random() * 500, this.FLOOR + 300, 700, true));
    }

    private addMorph(mesh: any, clip: THREE.AnimationClip, speed: number, duration: number, x: number, y: number, z: number, fudgeColor: boolean = false): void {
        if (!this.mixer) return;

        const clonedMesh = mesh.clone();
        clonedMesh.material = clonedMesh.material.clone();

        if (fudgeColor && clonedMesh.material instanceof THREE.Material) {
            (clonedMesh.material as any).color.offsetHSL(0, Math.random() * 0.5 - 0.25, Math.random() * 0.5 - 0.25);
        }

        (clonedMesh as any).speed = speed;

        this.mixer
            .clipAction(clip, clonedMesh)
            .setDuration(duration)
            .startAt(-duration * Math.random())
            .play();

        clonedMesh.position.set(x, y, z);
        clonedMesh.rotation.y = Math.PI / 2;
        clonedMesh.castShadow = true;
        clonedMesh.receiveShadow = true;

        this.scene.add(clonedMesh);
        this.morphs.push(clonedMesh);
        this.meshs.push(clonedMesh);
    }

    private setupRenderer(): void {
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setSize(this.screenWidth, this.screenHeight);
        this.container?.appendChild(this.renderer.domElement);

        this.renderer.autoClear = false;
        this.renderer.shadowMap.enabled = true;
        this.renderer.shadowMap.type = THREE.PCFShadowMap;
    }

    private setupControls(): void {
        if (!this.camera) return;

        this.controls = new FirstPersonControls(this.camera, this.renderer.domElement);
        this.controls.lookSpeed = 0.0125;
        this.controls.movementSpeed = 500;
        this.controls.lookVertical = true;
        this.controls.lookAt(this.scene.position);
    }

    private setupEventListeners(): void {
        window.addEventListener("resize", this.onWindowResize.bind(this));
        window.addEventListener("keydown", this.onKeyDown.bind(this));
    }

    private animate = (): void => {
        requestAnimationFrame(this.animate);
        this.render();
    };

    private render(): void {
        if (!this.camera) return;

        const delta = this.clock.getDelta();

        // 更新动画
        if (this.mixer) {
            this.mixer.update(delta);
        }

        // 更新变形物体位置
        this.morphs.forEach((morph) => {
            (morph as any).position.x += (morph as any).speed * delta;
            if ((morph as any).position.x > 2000) {
                (morph as any).position.x = -1000 - Math.random() * 500;
            }
        });

        // 更新控制器
        this.controls?.update(delta);

        // 渲染场景
        this.renderer.clear();
        this.renderer.render(this.scene, this.camera);

        // 渲染HUD
        if (this.showHUD && this.lightShadowMapViewer) {
            this.lightShadowMapViewer.render(this.renderer);
        }
    }

    private onWindowResize = (): void => {
        this.screenWidth = window.innerWidth;
        this.screenHeight = window.innerHeight;

        if (this.camera) {
            this.camera.aspect = this.screenWidth / this.screenHeight;
            this.camera.updateProjectionMatrix();
        }

        this.renderer.setSize(this.screenWidth, this.screenHeight);
        this.controls?.handleResize();
    };

    private onKeyDown = (event: KeyboardEvent): void => {
        switch (event.keyCode) {
            case 84: // 'T'键
                this.showHUD = !this.showHUD;
                break;
        }
    };

    public dispose(): void {
        // 移除事件监听器
        window.removeEventListener("resize", this.onWindowResize);
        window.removeEventListener("keydown", this.onKeyDown);

        // 停止动画循环
        cancelAnimationFrame(this.animate as unknown as number);

        // 移除渲染器DOM元素
        if (this.container && this.renderer.domElement.parentNode === this.container) {
            this.container.removeChild(this.renderer.domElement);
        }

        // 清理控制器
        this.controls?.dispose();

        // 清理场景对象
        this.meshs.forEach((mesh) => {
            this.scene.remove(mesh);

            // 清理几何体和材质
            if (mesh instanceof THREE.Mesh) {
                mesh.geometry.dispose();

                if (Array.isArray(mesh.material)) {
                    mesh.material.forEach((m) => m.dispose());
                } else {
                    mesh.material.dispose();
                }
            }
        });

        // 清理动画混合器
        if (this.mixer) {
            this.mixer.stopAllAction();
            this.mixer.uncacheRoot(this.scene);
        }

        // 清理渲染器
        this.renderer.dispose();

        // 清理HUD
        if (this.lightShadowMapViewer) {
            // ShadowMapViewer没有dispose方法，只需移除引用
            this.lightShadowMapViewer = null;
        }
    }
}

//小球
class Ball {
    // 场景属性
    private camera: THREE.PerspectiveCamera | null = null;
    private cameraOrtho: THREE.OrthographicCamera | null = null;
    private renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer();
    private scene: THREE.Scene = new THREE.Scene();
    private sceneOrtho: THREE.Scene = new THREE.Scene();
    private group: THREE.Group = new THREE.Group();

    // Sprite 相关属性
    private spriteTL: THREE.Sprite | null = null;
    private spriteTR: THREE.Sprite | null = null;
    private spriteBL: THREE.Sprite | null = null;
    private spriteBR: THREE.Sprite | null = null;
    private spriteC: THREE.Sprite | null = null;
    private mapC: THREE.Texture | null = null;

    // 容器引用
    private container: HTMLElement | null = null;

    constructor(id: string) {
        this.container = document.getElementById(id);
        this.load();
    }

    private load(): void {
        if (!this.container) {
            console.error(`ID属性未找到！`);
            return;
        }

        this.setupCameras();
        this.setupScene();
        this.setupSprites();
        this.setupRenderer();
        this.setupEventListeners();
        this.animate();
    }

    private setupCameras(): void {
        const width = window.innerWidth;
        const height = window.innerHeight;

        // 透视相机
        this.camera = new THREE.PerspectiveCamera(60, width / height, 1, 2100);
        this.camera.position.z = 1500;

        // 正交相机 (用于HUD)
        this.cameraOrtho = new THREE.OrthographicCamera(-width / 2, width / 2, height / 2, -height / 2, 1, 10);
        this.cameraOrtho.position.z = 10;
    }

    private setupScene(): void {
        this.scene.fog = new THREE.Fog(0x000000, 1500, 2100);
    }

    private setupSprites(): void {
        const amount = 200;
        const radius = 500;
        const textureLoader = new THREE.TextureLoader();

        // 加载HUD精灵图
        textureLoader.load("/img/sprite0.png", this.createHUDSprites.bind(this));

        // 加载其他精灵图
        const mapB = textureLoader.load("/img/sprite1.png");
        this.mapC = textureLoader.load("/img/sprite2.png");

        mapB.colorSpace = THREE.SRGBColorSpace;
        this.mapC.colorSpace = THREE.SRGBColorSpace;

        const materialC = new THREE.SpriteMaterial({
            map: this.mapC,
            color: 0xffffff,
            fog: true,
        });

        const materialB = new THREE.SpriteMaterial({
            map: mapB,
            color: 0xffffff,
            fog: true,
        });

        // 创建随机分布的精灵
        for (let a = 0; a < amount; a++) {
            const x = Math.random() - 0.5;
            const y = Math.random() - 0.5;
            const z = Math.random() - 0.5;

            let material: THREE.SpriteMaterial;
            if (z < 0) {
                material = materialB.clone();
            } else {
                material = materialC.clone();
                material.color.setHSL(0.5 * Math.random(), 0.75, 0.5);
                material.map?.offset.set(-0.5, -0.5);
                material.map?.repeat.set(2, 2);
            }

            const sprite = new THREE.Sprite(material);
            sprite.position.set(x, y, z);
            sprite.position.normalize();
            sprite.position.multiplyScalar(radius);
            this.group.add(sprite);
        }

        this.scene.add(this.group);
    }

    private createHUDSprites = (texture: THREE.Texture): void => {
        texture.colorSpace = THREE.SRGBColorSpace;
        const material = new THREE.SpriteMaterial({ map: texture });

        const width = texture.image?.width || 1;
        const height = texture.image?.height || 1;

        // 创建5个HUD精灵 (四个角落和中心)
        this.spriteTL = this.createHUDSprite(material, 0.0, 1.0, -width, height);
        this.spriteTR = this.createHUDSprite(material, 1.0, 1.0, width, height);
        this.spriteBL = this.createHUDSprite(material, 0.0, 0.0, -width, -height);
        this.spriteBR = this.createHUDSprite(material, 1.0, 0.0, width, -height);
        this.spriteC = this.createHUDSprite(material, 0.5, 0.5, 0, 0);

        this.updateHUDSprites();
    };

    private createHUDSprite(material: THREE.SpriteMaterial, centerX: number, centerY: number, posX: number, posY: number): THREE.Sprite {
        const sprite = new THREE.Sprite(material);
        sprite.center.set(centerX, centerY);
        sprite.scale.set(material.map?.image?.width || 1, material.map?.image?.height || 1, 1);
        sprite.position.set(posX, posY, 1);
        this.sceneOrtho.add(sprite);
        return sprite;
    }

    private updateHUDSprites(): void {
        const width = window.innerWidth / 2;
        const height = window.innerHeight / 2;

        if (this.spriteTL) this.spriteTL.position.set(-width, height, 1);
        if (this.spriteTR) this.spriteTR.position.set(width, height, 1);
        if (this.spriteBL) this.spriteBL.position.set(-width, -height, 1);
        if (this.spriteBR) this.spriteBR.position.set(width, -height, 1);
        if (this.spriteC) this.spriteC.position.set(0, 0, 1);
    }

    private setupRenderer(): void {
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.renderer.autoClear = false; // 允许在精灵球上渲染叠加层
        this.container?.appendChild(this.renderer.domElement);
    }

    private setupEventListeners(): void {
        window.addEventListener("resize", this.onWindowResize);
    }

    private onWindowResize = (): void => {
        const width = window.innerWidth;
        const height = window.innerHeight;

        // 更新透视相机
        if (this.camera) {
            this.camera.aspect = width / height;
            this.camera.updateProjectionMatrix();
        }

        // 更新正交相机
        if (this.cameraOrtho) {
            this.cameraOrtho.left = -width / 2;
            this.cameraOrtho.right = width / 2;
            this.cameraOrtho.top = height / 2;
            this.cameraOrtho.bottom = -height / 2;
            this.cameraOrtho.updateProjectionMatrix();
        }

        // 更新HUD精灵位置
        this.updateHUDSprites();

        // 更新渲染器尺寸
        this.renderer.setSize(width, height);
    };

    private animate = (): void => {
        requestAnimationFrame(this.animate);
        this.render();
    };

    private render(): void {
        if (!this.camera || !this.cameraOrtho) return;

        const time = Date.now() / 1000;

        // 更新精灵动画
        this.group.children.forEach((sprite, i) => {
            const material = (sprite as THREE.Sprite).material as THREE.SpriteMaterial;
            const scale = Math.sin(time + sprite.position.x * 0.01) * 0.3 + 1.0;

            const imageWidth = material.map?.image?.width || 1;
            const imageHeight = material.map?.image?.height || 1;

            material.rotation += 0.1 * (i / this.group.children.length);
            sprite.scale.set(scale * imageWidth, scale * imageHeight, 1.0);

            if (material.map !== this.mapC) {
                material.opacity = Math.sin(time + sprite.position.x * 0.01) * 0.4 + 0.6;
            }
        });

        // 旋转整个精灵组
        this.group.rotation.x = time * 0.5;
        this.group.rotation.y = time * 0.75;
        this.group.rotation.z = time * 1.0;

        // 渲染场景
        this.renderer.clear();
        this.renderer.render(this.scene, this.camera);
        this.renderer.clearDepth();
        this.renderer.render(this.sceneOrtho, this.cameraOrtho);
    }

    public dispose(): void {
        // 移除事件监听器
        window.removeEventListener("resize", this.onWindowResize);

        // 停止动画循环
        cancelAnimationFrame(this.animate as unknown as number);

        // 移除渲染器DOM元素
        if (this.container && this.renderer.domElement.parentNode === this.container) {
            this.container.removeChild(this.renderer.domElement);
        }

        // 清理纹理
        [this.mapC].forEach((texture) => {
            if (texture) texture.dispose();
        });

        // 清理精灵材质
        const disposeSprite = (sprite: THREE.Sprite | null) => {
            if (sprite) {
                (sprite.material as THREE.Material).dispose();
                if (sprite.material.map) {
                    sprite.material.map.dispose();
                }
            }
        };

        disposeSprite(this.spriteTL);
        disposeSprite(this.spriteTR);
        disposeSprite(this.spriteBL);
        disposeSprite(this.spriteBR);
        disposeSprite(this.spriteC);

        // 清理组中的精灵
        this.group.children.forEach((child) => {
            const sprite = child as THREE.Sprite;
            sprite.material.dispose();
            if (sprite.material.map) {
                sprite.material.map.dispose();
            }
        });

        // 清理渲染器
        this.renderer.dispose();
    }
}

//立方体地图
class CubeMap {
    // 场景对象
    private cube: THREE.Mesh | null = null;
    private sphere: THREE.Mesh | null = null;
    private torus: THREE.Mesh | null = null;
    private material: THREE.MeshStandardMaterial | null = null;
    private cubeCamera: THREE.CubeCamera | null = null;
    private controls: OrbitControls | null = null;
    private meshs: THREE.Object3D[] = [];

    // Three.js 核心对象
    private cubeRenderTarget: THREE.WebGLCubeRenderTarget = new THREE.WebGLCubeRenderTarget(256);
    private scene: THREE.Scene = new THREE.Scene();
    private camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
    private renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer({ antialias: true });

    // 容器引用
    private container: HTMLElement | null = null;

    constructor(id: string) {
        this.container = document.getElementById(id);
        this.load();
    }

    private load(): void {
        if (!this.container) {
            console.error(`ID属性未找到！`);
            return;
        }

        this.setupRenderer();
        this.setupScene();
        this.setupObjects();
        this.setupControls();
        this.setupEventListeners();
    }

    private setupRenderer(): void {
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.renderer.setAnimationLoop(this.animation.bind(this));
        this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
        this.container?.appendChild(this.renderer.domElement);
    }

    private setupScene(): void {
        this.camera.position.z = 75;
        this.scene.rotation.y = 0.5; // 避免飞行物体遮挡太阳

        // 加载HDR环境贴图
        new RGBELoader().load(
            "/file/quarry_01_1k.hdr",
            (texture: THREE.Texture) => {
                texture.mapping = THREE.EquirectangularReflectionMapping;
                this.scene.background = texture;
                this.scene.environment = texture;
            },
            undefined,
            (error) => {
                console.error("HDR加载失败:", error);
            }
        );
    }

    private setupObjects(): void {
        // 设置立方体渲染目标
        this.cubeRenderTarget.texture.type = THREE.HalfFloatType;
        this.cubeCamera = new THREE.CubeCamera(1, 1000, this.cubeRenderTarget);

        // 创建反射材质
        this.material = new THREE.MeshStandardMaterial({
            envMap: this.cubeRenderTarget.texture,
            roughness: 0.05,
            metalness: 1,
        });

        // 创建球体
        this.sphere = new THREE.Mesh(new THREE.IcosahedronGeometry(15, 8), this.material);
        this.meshs.push(this.sphere);
        this.scene.add(this.sphere);

        // 创建其他材质
        const material2 = new THREE.MeshStandardMaterial({
            roughness: 0.1,
            metalness: 0,
        });

        // 创建立方体
        this.cube = new THREE.Mesh(new THREE.BoxGeometry(15, 15, 15), material2);
        this.meshs.push(this.cube);
        this.scene.add(this.cube);

        // 创建圆环结
        this.torus = new THREE.Mesh(new THREE.TorusKnotGeometry(8, 3, 128, 16), material2);
        this.meshs.push(this.torus);
        this.scene.add(this.torus);
    }

    private setupControls(): void {
        if (!this.renderer.domElement) return;

        this.controls = new OrbitControls(this.camera, this.renderer.domElement);
        this.controls.autoRotate = true;
    }

    private setupEventListeners(): void {
        window.addEventListener("resize", this.onWindowResized.bind(this));
    }

    private onWindowResized = (): void => {
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
    };

    private animation = (msTime: number): void => {
        const time = msTime / 1000;

        // 更新立方体位置和旋转
        if (this.cube) {
            this.cube.position.x = Math.cos(time) * 30;
            this.cube.position.y = Math.sin(time) * 30;
            this.cube.position.z = Math.sin(time) * 30;
            this.cube.rotation.x += 0.02;
            this.cube.rotation.y += 0.03;
        }

        // 更新圆环结位置和旋转
        if (this.torus) {
            this.torus.position.x = Math.cos(time + 10) * 30;
            this.torus.position.y = Math.sin(time + 10) * 30;
            this.torus.position.z = Math.sin(time + 10) * 30;
            this.torus.rotation.x += 0.02;
            this.torus.rotation.y += 0.03;
        }

        // 更新立方体相机
        if (this.cubeCamera) {
            this.cubeCamera.update(this.renderer, this.scene);
        }

        // 更新控制器
        this.controls?.update();

        // 渲染场景
        this.renderer.render(this.scene, this.camera);
    };

    public dispose(): void {
        // 移除事件监听器
        window.removeEventListener("resize", this.onWindowResized);

        // 停止动画循环
        this.renderer.setAnimationLoop(null);

        // 移除渲染器DOM元素
        if (this.container && this.renderer.domElement.parentNode === this.container) {
            this.container.removeChild(this.renderer.domElement);
        }

        // 清理控制器
        this.controls?.dispose();

        // 清理几何体和材质
        this.meshs.forEach((mesh) => {
            this.scene.remove(mesh);

            if (mesh instanceof THREE.Mesh) {
                mesh.geometry.dispose();

                if (Array.isArray(mesh.material)) {
                    mesh.material.forEach((m) => m.dispose());
                } else {
                    mesh.material.dispose();
                }
            }
        });

        // 清理立方体相机和渲染目标
        if (this.cubeCamera) {
            this.scene.remove(this.cubeCamera);
        }
        //this.cubeRenderTarget.dispose();

        // 清理环境贴图
        if (this.scene.background instanceof THREE.Texture) {
            this.scene.background.dispose();
        }
        if (this.scene.environment instanceof THREE.Texture) {
            this.scene.environment.dispose();
        }

        // 清理渲染器
        this.renderer.dispose();
    }
}

//大海
class Sea {
    // 场景对象
    private controls: OrbitControls | null = null;
    private water: Water | null = null;
    private mesh: THREE.Mesh | null = null;
    private meshs: THREE.Object3D[] = [];
    private camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 1, 20000);
    private scene: THREE.Scene = new THREE.Scene();
    private sun: THREE.Vector3 = new THREE.Vector3();
    private renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer();

    // 环境相关
    private pmremGenerator: THREE.PMREMGenerator;
    private sceneEnv: THREE.Scene = new THREE.Scene();
    private renderTarget: THREE.WebGLRenderTarget | null = null;

    // 容器引用
    private container: HTMLElement | null = null;

    constructor(id: string) {
        this.pmremGenerator = new THREE.PMREMGenerator(this.renderer);
        this.container = document.getElementById(id);
        this.load();
    }

    private load(): void {
        if (!this.container) {
            console.error(`ID属性未找到！`);
            return;
        }

        this.setupRenderer();
        this.setupCamera();
        this.setupWater();
        this.setupSky();
        this.setupMesh();
        this.setupControls();
        this.setupEventListeners();
        this.animate();
    }

    private setupRenderer(): void {
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
        this.renderer.toneMappingExposure = 0.5;
        this.container?.appendChild(this.renderer.domElement);
    }

    private setupCamera(): void {
        this.camera.position.set(30, 30, 100);
    }

    private setupWater(): void {
        const waterGeometry = new THREE.PlaneGeometry(10000, 10000);

        const waterNormals = new THREE.TextureLoader().load("/img/waternormals.jpg", (texture) => {
            texture.wrapS = THREE.RepeatWrapping;
            texture.wrapT = THREE.RepeatWrapping;
        });

        this.water = new Water(waterGeometry, {
            textureWidth: 512,
            textureHeight: 512,
            waterNormals: waterNormals,
            sunDirection: new THREE.Vector3(),
            sunColor: 0xffffff,
            waterColor: 0x001e0f,
            distortionScale: 3.7,
            fog: this.scene.fog !== undefined,
        });

        this.water.rotation.x = -Math.PI / 2;
        this.scene.add(this.water);
        this.meshs.push(this.water);
    }

    private setupSky(): void {
        const sky = new Sky();
        sky.scale.setScalar(10000);
        this.scene.add(sky);
        this.meshs.push(sky);

        const skyUniforms = sky.material.uniforms;
        skyUniforms["turbidity"].value = 10;
        skyUniforms["rayleigh"].value = 2;
        skyUniforms["mieCoefficient"].value = 0.005;
        skyUniforms["mieDirectionalG"].value = 0.8;

        this.updateSun(2, 180);
    }

    private updateSun(elevation: number, azimuth: number): void {
        const phi = THREE.MathUtils.degToRad(90 - elevation);
        const theta = THREE.MathUtils.degToRad(azimuth);
        this.sun.setFromSphericalCoords(1, phi, theta);

        const sky = this.meshs.find((m) => m instanceof Sky) as Sky;
        if (sky) {
            sky.material.uniforms["sunPosition"].value.copy(this.sun);
        }

        if (this.water) {
            this.water.material.uniforms["sunDirection"].value.copy(this.sun).normalize();
        }

        if (this.renderTarget) {
            this.renderTarget.dispose();
        }

        this.sceneEnv.children = [];
        const skyClone = sky.clone();
        this.sceneEnv.add(skyClone);

        this.renderTarget = this.pmremGenerator.fromScene(this.sceneEnv);
        this.scene.environment = this.renderTarget.texture;
    }

    private setupMesh(): void {
        const geometry = new THREE.BoxGeometry(30, 30, 30);
        const material = new THREE.MeshStandardMaterial({ roughness: 0 });
        this.mesh = new THREE.Mesh(geometry, material);
        this.scene.add(this.mesh);
        this.meshs.push(this.mesh);
    }

    private setupControls(): void {
        if (!this.renderer.domElement) return;

        this.controls = new OrbitControls(this.camera, this.renderer.domElement);
        this.controls.maxPolarAngle = Math.PI * 0.495;
        this.controls.target.set(0, 10, 0);
        this.controls.minDistance = 40.0;
        this.controls.maxDistance = 200.0;
        this.controls.update();
    }

    private setupEventListeners(): void {
        window.addEventListener("resize", this.onWindowResize.bind(this));
    }

    private onWindowResize = (): void => {
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(window.innerWidth, window.innerHeight);
    };

    private animate = (): void => {
        requestAnimationFrame(this.animate);
        this.render();
    };

    private render = (): void => {
        const time = performance.now() * 0.001;

        // 更新网格动画
        if (this.mesh) {
            this.mesh.position.y = Math.sin(time) * 20 + 5;
            this.mesh.rotation.x = time * 0.5;
            this.mesh.rotation.z = time * 0.51;
        }

        // 更新水面动画
        if (this.water) {
            this.water.material.uniforms["time"].value += 1.0 / 60.0;
        }

        // 渲染场景
        this.renderer.render(this.scene, this.camera);
    };

    public dispose(): void {
        // 移除事件监听器
        window.removeEventListener("resize", this.onWindowResize);

        // 停止动画循环
        cancelAnimationFrame(this.animate as unknown as number);

        // 移除渲染器DOM元素
        if (this.container && this.renderer.domElement.parentNode === this.container) {
            this.container.removeChild(this.renderer.domElement);
        }

        // 清理控制器
        this.controls?.dispose();

        // 清理场景对象
        this.meshs.forEach((mesh) => {
            this.scene.remove(mesh);

            if (mesh instanceof THREE.Mesh) {
                mesh.geometry.dispose();

                if (Array.isArray(mesh.material)) {
                    mesh.material.forEach((m) => m.dispose());
                } else {
                    mesh.material.dispose();
                }
            }
        });

        // 清理水面
        if (this.water) {
            this.scene.remove(this.water);
            this.water.material.dispose();
            (this.water.geometry as THREE.BufferGeometry).dispose();
        }

        // 清理环境贴图
        if (this.renderTarget) {
            this.renderTarget.dispose();
        }
        this.pmremGenerator.dispose();

        if (this.scene.environment) {
            (this.scene.environment as THREE.Texture).dispose();
        }

        // 清理渲染器
        this.renderer.dispose();
    }
}

//蹦迪女孩
class DiscoGirl {
    private mesh: THREE.SkinnedMesh | null = null;
    private camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
    private scene: THREE.Scene = new THREE.Scene();
    private renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer({ antialias: true });
    private effect: OutlineEffect | null = null;
    private helper: MMDAnimationHelper | null = new MMDAnimationHelper();
    private clock: THREE.Clock = new THREE.Clock();
    private loader: MMDLoader = new MMDLoader();
    private container: HTMLElement | null = null;
    private animationId: number | null = null;
    private ammo: any | null = null;

    constructor(id: string) {
        this.container = document.getElementById(id);
        if (!this.container) {
            console.error(`ID属性未找到！`);
            return;
        }
        this.initAmmoLoader().then(() => this.load());
    }

    private async initAmmoLoader(): Promise<void> {
        if (this.ammo) return this.ammo;
        return new Promise((resolve, reject) => {
            const script = document.createElement("script");
            script.src = "/js/ammo.wasm.js";

            script.onload = async () => {
                try {
                    const Ammo = (window as any).Ammo;
                    this.ammo = await Ammo();
                    resolve(this.ammo);
                } catch (error) {
                    reject(error);
                }
            };

            script.onerror = reject;
            document.head.appendChild(script);
        });
    }

    private load(): void {
        // 场景设置
        this.scene.background = new THREE.Color(0xffffff);
        this.scene.add(new THREE.PolarGridHelper(30, 0));

        // 相机设置
        this.scene.add(this.camera);

        // 光照设置
        const ambient = new THREE.AmbientLight(0xaaaaaa, 3);
        this.scene.add(ambient);

        const directionalLight = new THREE.DirectionalLight(0xffffff, 3);
        directionalLight.position.set(-1, 1, 1).normalize();
        this.scene.add(directionalLight);

        // 渲染器设置
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.container?.appendChild(this.renderer.domElement);

        // 轮廓效果
        this.effect = new OutlineEffect(this.renderer);

        // 加载模型和动画
        this.loadWithAnimation();

        // 事件监听
        window.addEventListener("resize", this.onWindowResize.bind(this));

        // 开始动画循环
        this.animate();
    }

    private loadWithAnimation(): void {
        this.loader.loadWithAnimation(
            "/file/miku_v2.pmd",
            "/file/wavefile_v2.vmd",
            (mmd) => {
                this.mesh = mmd.mesh;

                // 确保物理引擎已初始化
                if (this.ammo) {
                    this.helper?.add(this.mesh, {
                        animation: mmd.animation,
                        physics: true,
                    });
                    this.loadAnimation();
                } else {
                    console.error("Ammo未初始化");
                }
            },
            this.onProgress,
            (error) => {
                console.error("加载模块错误：", error);
            }
        );
    }

    private loadAnimation(): void {
        this.loader.loadAnimation(
            "/file/wavefile_camera.vmd",
            this.camera,
            (cameraAnimation) => {
                const params: any = { animation: cameraAnimation };
                this.helper?.add(this.camera, params);

                if (this.mesh) {
                    this.scene.add(this.mesh);
                }
            },
            this.onProgress,
            (error) => {
                console.error("加载失败:", error);
            }
        );
    }

    //加载进度回调
    private onProgress = (xhr: ProgressEvent): void => {
        if (xhr.lengthComputable) {
            const percentComplete = (xhr.loaded / xhr.total) * 100;
            console.log(Math.round(percentComplete) + "% downloaded");
        }
    };

    private onWindowResize = (): void => {
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        this.effect?.setSize(window.innerWidth, window.innerHeight);
    };

    private animate = (): void => {
        this.animationId = requestAnimationFrame(this.animate);
        this.render();
    };

    private render(): void {
        this.helper?.update(this.clock.getDelta());
        // 遍历场景中的所有对象检查
        this.scene.traverse((obj) => {
            if (obj instanceof THREE.Line || obj instanceof THREE.LineSegments) {
                obj.visible = false; // 隐藏所有线对象
            }
        });
        this.effect?.render(this.scene, this.camera);
    }

    public dispose(): void {
        // 1. 停止动画循环
        if (this.animationId !== null) {
            cancelAnimationFrame(this.animationId);
            this.animationId = null;
        }

        // 2. 清理场景
        if (this.mesh) {
            this.scene.remove(this.mesh);
            if (this.mesh instanceof THREE.Mesh) {
                this.mesh.geometry.dispose();
                if (Array.isArray(this.mesh.material)) {
                    this.mesh.material.forEach((m) => m.dispose());
                } else {
                    this.mesh.material.dispose();
                }
            }
        }

        // 3. 清理渲染器2
        this.renderer.dispose();

        // 4. 移除DOM元素
        if (this.container && this.renderer.domElement.parentNode === this.container) {
            this.container.removeChild(this.renderer.domElement);
        }

        // 7. 移除事件监听
        window.removeEventListener("resize", this.onWindowResize);

        // 8. 重置状态
        this.helper = null;
        this.mesh = null;
    }
}

export {
    House, //房子背景
    Coaster, //过山车背景
    Dancer, //跳舞背景
    Points, //多彩圆点
    Horse, //万马奔腾
    Ball, //小球
    CubeMap, //立方体地图
    Sea, //大海
    DiscoGirl, //蹦迪女孩
};
